<?php

namespace app\admin\controller\cha;

use app\admin\controller\BaseController;
use app\common\model\Channel;
use app\common\model\ExpressAttr;
use app\common\model\ExpressCountry;
use app\common\model\ProductPlatformSku;
use app\common\model\SysCountries;
use app\common\service\product\CalculatePrePriceService;
use app\common\service\logistics\ChannelService;
use think\Db;
use think\facade\Validate;

/**
 * 运费计算
 * Class ExpressFreightCalculateController
 * @package app\admin\controller\cha
 */
class ExpressFreightCalculateController extends BaseController
{
    /**
     * 运费计算首页
     * @return mixed
     */
    public function index()
    {
        //不是搜索调用，直接展示页面
        if(!$this->request->isAjax()) {

            //国家
            $this->assign('countries', SysCountries::all());
            //sku
            $this->assign('skus', ProductPlatformSku::all());
            
            return $this->fetch('index');
        }
        
        ######  物流推荐 + 运费算法 开始 ↓  ######
        /*
         * 三种模式
         * ①订单模式：【订单号】根据订单号查询运费所需字段
         * ②重量模式：【国家、重量（单位g）】
         * ③商品模式：【国家、SKU、数量】
         */
        
        ##计算元素【重量、运费、挂号费、超重重量、超重费】
        ##包裹重量32.4Kg，包裹费用=32.4*运费+挂号费+超重重量（32.4kg-30kg-0.05kg=2.35kg，向上取整为3kg）*50
        
        //注：计算时，重量单位需转成KG
        
        //搜索查询，获取必要信息进行计算
        $type = $this->request->get('type','','trim'); //计算模式
        $orderID = $this->request->post('order_sn','','trim'); //订单ID
        $countryCode = $this->request->post('country_code','','trim'); //国家二字编码
        $weight = $this->request->post('weight','','intval'); //重量
        $sku = $this->request->post('sku','','trim');
        
        #模式① 后续需要时在开发
        if($type == 'order'){
            //todo 获取订单上的收货国家和商品重量
            $countryCode = '订单上的国家';
            $weight = '订单上的商品重量';
            //todo 根据国家获取可行的物流列表
            //todo 对每个物流，执行计算，得出运费和时间
            //todo 执行计算
            return $this->fetch('lists');
        }
        
        #模式②
        if($type == 'weight'){
            
            #1.根据国家获取可行的物流列表
           $expressCountry = CalculatePrePriceService::getShippingCostList($countryCode, $weight);
            
            $this->assign('list', $expressCountry);
            return $this->fetch('lists');
        }
        
        #模式③ 注：可能会存在多个sku
        if($type == 'sku'){

            $data = $this->request->only(['sku', 'qty'], 'post');
            $data = ChannelService::getInstance()->transformToArray($data);
            var_dump($data,$sku);die;
            //todo 根据sku获取商品重量
            //todo 根据国家获取可行的物流列表
            //todo 对每个物流，执行计算，得出运费和时间
            return $this->fetch('lists');
        }

        ######  物流推荐 + 运费算法 结束 ↓  ######
        
        //不符合上面模式的直接返回错误
        $this->error('请输入您要计算的数据');
        
    }

    public function preSalePrice(){

        $costPrice = $this->request->post('cost_price','','trim'); //拿货价
        $countryCode = $this->request->post('order_country_code','','trim'); //国家二字编码
        $weight = $this->request->post('order_weight','','intval'); //重量
        ###获取国家信息【税率、使用币种】
        $countryInfo = SysCountries::where('code_two',$countryCode)->select()->toArray();
        //var_dump($countryInfo);die;

        ###计算运费，取第一条（最便宜那条）
        #1.根据国家获取可行的物流列表
        $expressCountry = ExpressCountry::with('quotation')->all(['country_code' => $countryCode])->each(function ($v,$k) use($weight)
        {
            #2.对每个物流，执行计算，得出运费和时间
            //整合f返回数据所需字段【物流编号、渠道、承诺天数、平均时效/天、妥投率、最大重量、是否超重、运费】
            $v['channel'] = Channel::getNameById($v['channel_id']); //渠道
            $v['end_weight'] = '未知'; //最大重量
            $v['is_overweight'] = '未知'; //是否超重
            $v['express_freight'] = 0; //运费

            #根据重量匹配合适的区间报价单，如果没有匹配的，默认取最后一条报价单（最后一条是最重的一条报价单）
            $qCount = $v->quotation->count(); //报价单总数
            $qArr = $v->quotation->toArray();
            $q = []; //匹配重量的报价单
            foreach ($qArr as $qk=>$qv ){
                if(($qv['start_weight'] < $weight && $weight <= $qv['end_weight']) || ($qk == $qCount - 1) ){
                    $q = $qv;
                    break;
                }
            }

            //没有报价单，直接跳过
            if(empty($q)) return $v;

            $isOverweight = ($weight - $q['end_weight']) > 0 ? true : false; //是否超重（上下浮动50g）
            $expressFreight = 0; //运费结果
            if($isOverweight){
                ##超重算法（重量单位转Kg）【重量*运费 + 挂号费 + 向上取整（重量 - 结束重量 - 0.05kg[边界允许值]）*超重运费】
                $expressFreight = ($weight/1000)*$q['price'] + $q['register_price'] + $q['continue_weight_price']*ceil(($weight - $q['end_weight'] - 50)/1000);

                //echo "超重算法".PHP_EOL;
                //echo $expressFreight;
            }
            else{
                ##标准算法（重量单位转Kg）【重量*运费+挂号费
                $expressFreight = ($weight/1000)*$q['price'] + $q['register_price'];

                //echo "标准算法".PHP_EOL;
                //echo $expressFreight;
            }

            $v['end_weight'] = $q['end_weight'];
            $v['is_overweight'] = $isOverweight ? '是' : "否";
            $v['express_freight'] = $expressFreight;
            return $v;

        })->toArray();
        //排序【按运费的从低到高排序，用<,反之用>】
        usort($expressCountry, function($a, $b) {
            if ($a['express_freight'] == $b['express_freight']) {
                return 0;
            }
            return ($a['express_freight'] < $b['express_freight']) ? -1 : 1;
        });
        $ec = current($expressCountry);

        ###成交费（亚马逊佣金）

        ###预设退款（订单总价3%）基础值=[拿货价+运费+成交费]

        ###税费（国家税费）基础值=[拿货价+运费+成交费]
        $countryTaxRate = $countryInfo['tax_rate']; //国家税率

        ###预设广告费（初定0）
        $preAdPrice = 0;

        ###其他费用（什么打包费，包装法，注册公司费用等等，初始值1000（取1%） 相当于，每个取10块）
        $otherPrice = 10;

        ###预定价成本算法
        //【成本=拿货价+运费+成交费（亚马逊佣金）+ 预设退款（订单总价%）+ 税费（国家税费） + 预设广告费（）+ 其他费用】
        $preSalePrice = $costPrice + $ec['express_freight'] + $preAdPrice + $otherPrice ;


        $res = [
            'express_country_id' => $ec['express_country_id'],
            'channel' => $ec['channel'],
            'promise_day' => $ec['promise_day'],
            'average_aging' => $ec['average_aging'],
            'delivery_rate' => $ec['delivery_rate'],
            'express_freight' => $ec['express_freight'],
            'pre_sale_price' => $preSalePrice,
            'country_pre_sale_price' => $preSalePrice,
        ];
        $this->assign('res', $res);
        return $this->fetch('pre_sale_price');
    }
}
